package com.fqgj.sentry.policy.server.policy;

import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.JSONUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.sentry.common.cache.RequestLocalInfo;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.exception.enums.ErrorCodeEnums;
import com.fqgj.sentry.policy.dao.*;
import com.fqgj.sentry.policy.domain.policy.PolicyUpdate;
import com.fqgj.sentry.policy.entity.*;
import com.fqgj.sentry.policy.enums.ActiveEnum;
import com.fqgj.sentry.policy.enums.PolicyMatchingTypeEnum;
import com.fqgj.sentry.policy.enums.PolicyTypeEnum;
import com.fqgj.sentry.policy.enums.RuleConditionTypeEnum;
import com.fqgj.sentry.policy.exception.PolicyErrorCodeEnums;
import com.fqgj.sentry.policy.server.policy.data.Decision;
import com.fqgj.sentry.policy.server.policy.data.Weight;
import com.fqgj.log.interfaces.Log;
import com.fqgj.log.factory.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: lpp
 * Date: 2017/7/13
 * Time: 下午9:43
 */
@Service
@Transactional
public class PolicyUpdateDeletedService {
    public static final Log LOGGER = LogFactory.getLog(PolicyUpdateDeletedService.class);

    @Autowired
    private PcPolicyDao pcPolicyDao;
    @Autowired
    private PcRuleDao pcRuleDao;
    @Autowired
    private PcColumnDao columnDao;
    @Autowired
    private PcRuleConditionDao ruleConditionDao;
    @Autowired
    private PcExecuteResultDao executeResultDao;


    /**
     * 策略 修改
     *
     * @param policy
     * @return
     */
    public Boolean update(Long policyId, PolicyUpdate policy) {
        PcPolicyEntity pcPolicyEntity = pcPolicyDao.selectByPrimaryKey(policyId);
        if (pcPolicyEntity == null) {
            throw new BizException(PolicyErrorCodeEnums.policy_not_exist_error);
        }
        if (policy.getMatchingTypeEnum() == PolicyMatchingTypeEnum.weight_match) {
            if (StringUtils.isEmpty(policy.getWeightRange())) {
                throw new BizException(PolicyErrorCodeEnums.policy_weight_not_exist_error);
            } else {
                pcPolicyEntity.setWeightRange(policy.getWeightRange());
            }
        }
        if (pcPolicyEntity.getType() == PolicyTypeEnum.grade.getType()) {
            if (policy.getMatchingTypeEnum() != PolicyMatchingTypeEnum.score) {
                throw new BizException(PolicyErrorCodeEnums.policy_score_match_change_error);
            }
            pcPolicyEntity.setBaseScore(BigDecimal.valueOf(Double.valueOf(policy.getBaseScore())));
            pcPolicyEntity.setColumnName(policy.getColumnName());
        }
        //如果是规则组  修改匹配模式
        if (pcPolicyEntity.getType() == PolicyTypeEnum.rules.getType()) {
            if (policy.getMatchingTypeEnum().getType() != pcPolicyEntity.getMatchingType()) {
                List<PcRuleEntity> ruleEntityList = pcRuleDao.selectListByPolicyId(policyId, ActiveEnum.all.getType(), com.fqgj.sentry.policy.enums.RuleTypeEnum.custom.getType());
                if (CollectionUtils.isNotEmpty(ruleEntityList)) {
                    //修改  策略规则的条件
                    for (PcRuleEntity ruleEntity : ruleEntityList) {
                        //查询 该规则下的条件
                        PcRuleConditionEntity conditionEntity = ruleConditionDao.selectByRuleId(ruleEntity.getId());
                        String condition = "";
                        RuleConditionTypeEnum ruleConditionTypeEnum = RuleConditionTypeEnum.getEnumByType(pcPolicyEntity.getMatchingType());
                        switch (ruleConditionTypeEnum) {
                            case first_match:
                                condition = conditionEntity.getFirstCondition();
                                break;
                            case bad_match:
                                condition = conditionEntity.getWorstCondition();
                                break;
                            case weight_match:
                                condition = conditionEntity.getWeightCondition();
                                break;
                        }
                        //现在改为权重匹配
                        String nowCondition = condition;
                        if (policy.getMatchingTypeEnum() == PolicyMatchingTypeEnum.weight_match) {
                            Map conditionMap = new HashMap();
                            try {
                                conditionMap = JSONUtils.json2map(condition);
                                conditionMap.put("weight", new Weight("weightScore", null, Arrays.asList(10, 0)));
                                conditionMap.put("hitDecisionOption", null);
                                nowCondition = JSONUtils.obj2json(conditionMap);
                            } catch (Exception e) {
                                throw new BizException(ErrorCodeEnums.json_transform_error);
                            }
                        }
                        //如果 之前的条件是 权重分
                        if (pcPolicyEntity.getMatchingType() == PolicyMatchingTypeEnum.weight_match.getType()) {
                            Map conditionMap = new HashMap();
                            try {
                                //查询该策略 结果的
                                PcExecuteResultEntity executeResultEntity = executeResultDao.selectMaxLevelExecuteResultList(ruleEntity.getPolicySetsId());
                                if (executeResultEntity == null) {
                                    throw new BizException(PolicyErrorCodeEnums.policy_not_exist_result_error);
                                }
                                conditionMap = JSONUtils.json2map(condition);
                                conditionMap.put("weight", null);
                                conditionMap.put("hitDecisionOption", new Decision(Integer.valueOf(executeResultEntity.getId().toString()), "reject", 1));
                                nowCondition = JSONUtils.obj2json(conditionMap);
                            } catch (Exception e) {
                                throw new BizException(ErrorCodeEnums.json_transform_error);
                            }
                        }

                        RuleConditionTypeEnum conditionTypeEnum = RuleConditionTypeEnum.getEnumByType(policy.getMatchingTypeEnum().getType());
                        switch (conditionTypeEnum) {
                            case first_match:
                                if (StringUtils.isEmpty(conditionEntity.getFirstCondition())) {
                                    conditionEntity.setFirstCondition(nowCondition).setConditionType(RuleConditionTypeEnum.first_match.getType());
                                }
                                break;
                            case bad_match:
                                if (StringUtils.isEmpty(conditionEntity.getWorstCondition())) {
                                    conditionEntity.setWorstCondition(nowCondition).setConditionType(RuleConditionTypeEnum.bad_match.getType());
                                }
                                break;
                            case weight_match:
                                if (StringUtils.isEmpty(conditionEntity.getWeightCondition())) {
                                    conditionEntity.setWeightCondition(nowCondition).setConditionType(RuleConditionTypeEnum.weight_match.getType());
                                }
                                break;
                        }
                        ruleConditionDao.updateByPrimaryKey(conditionEntity);
                    }
                }
            } else {
                //评分卡  对字段进行修改
                PcColumnEntity columnEntity = columnDao.selectByMerchantIdAndColumnCode(RequestLocalInfo.getCurrentMerchantId(),
                        pcPolicyEntity.getColumnCode());
                if (columnEntity != null) {
                    columnEntity.setDisplayName(policy.getColumnName());
                    columnDao.updateByPrimaryKey(columnEntity);
                }
            }

        } else {
            //评分卡  对字段进行修改
            PcColumnEntity columnEntity = columnDao.selectByMerchantIdAndColumnCode(RequestLocalInfo.getCurrentMerchantId(),
                    pcPolicyEntity.getColumnCode());
            if (columnEntity != null) {
                columnEntity.setDisplayName(policy.getColumnName());
                columnDao.updateByPrimaryKey(columnEntity);
            }
        }
        pcPolicyEntity.setName(policy.getName())
                .setMatchingType(policy.getMatchingTypeEnum().getType())
                .setInfo(policy.getInfo());
        return pcPolicyDao.updateByPrimaryKey(pcPolicyEntity) != null;

    }

    /**
     * 策略删除
     *
     * @param merchantId
     * @param policyId
     * @return
     */
    public Boolean delete(Long merchantId, Long policyId) {
        PcPolicyEntity policyEntity = pcPolicyDao.selectByPrimaryKey(policyId);
        if (policyEntity == null) {
            throw new BizException(PolicyErrorCodeEnums.policy_not_exist_error);
        }
        if (CollectionUtils.isNotEmpty(pcRuleDao.selectListByPolicyId(policyId, ActiveEnum.all.getType(), com.fqgj.sentry.policy.enums.RuleTypeEnum.all.getType()))) {
            throw new BizException(PolicyErrorCodeEnums.policy_exist_rule_error);
        }
        //如果该策略为评分卡  删除字段记录
        if (PolicyTypeEnum.grade.getType() == policyEntity.getType()) {
            //删除字段表的一个字段
            columnDao.deleteBuColumnCode(merchantId, policyEntity.getColumnCode());
        }
        //删除 策略
        return pcPolicyDao.deleteByPrimaryKey(policyId) > 0;
    }

}
